/*
 * @Copyright: 2017 www.yyfax.com Inc. All rights reserved.
 */
package com.jaws.core.compatible.spring.resolver;

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Conventions;
import org.springframework.core.MethodParameter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver;

import com.jaws.core.common.util.JacksonUtil;
import com.jaws.core.compatible.spring.annotation.JsonParam;


/**
 * form提交JSON参数
 * 
 * @author jiangmy
 * @date 2017-04-12 16:14:39
 * @since v1.0.0
 */
@Component
public class JsonParamResolver extends AbstractMessageConverterMethodArgumentResolver {
	
	private static final Logger logger = LoggerFactory.getLogger(JsonParamResolver.class);
	
	/**
	 * @param converters
	 */
	public JsonParamResolver(List<HttpMessageConverter<?>> converters) {
		super(converters);
	}

	@Override
	public boolean supportsParameter(MethodParameter parameter) {
		return parameter.getParameterAnnotation(JsonParam.class) != null;
	}

	@Override
	public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest,
			WebDataBinderFactory binderFactory) throws Exception {

		HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
		String json = request.getParameter(parameter.getParameterName());
		logger.debug("解析JSON参数:{} = {}", parameter.getParameterName(), json);
		
		Class<?> parameterType = parameter.getParameterType();
		Object arg = null;
		if (StringUtils.isNoneBlank(json) && parameterType != null) {
		// 解析
			arg = JacksonUtil.fromJson(json, parameterType);
		}

		String name = Conventions.getVariableNameForParameter(parameter);

		WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name);
		if (arg != null) {
			validateIfApplicable(binder, parameter);
			if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
				throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());
			}
		}
		mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());
		
		return arg;
	}
}